#define _GNU_SOURCE
#include "app_deviece.h"
#include "app_common.h"
#include "app_message.h"
#include "app_pool.h"
#include "app_mqtt.h"
#include "fcntl.h"
#include "unistd.h"
#include "log/log.h"
#include "app_buff.h"
#define BUFFER_SIZE 1024
static Device *device;
//初始化设备
Device *app_device_init(char *filename)
{
    //申请内存
    device = (Device *)malloc(sizeof(Device));
    //初始化属性
    device->filename = filename;
    device->fd = open(filename, O_RDWR,0644);//当前用户可读可写，其他可读
    device->up_buf = app_buffer_init(BUFFER_SIZE);
    device->down_buf = app_buffer_init(BUFFER_SIZE);
    device->is_running = 0;
    device->last_write_time = 0;
    device->post_read = NULL;
    device->post_write = NULL;
    //初始化线程吃
    app_pool_init(5);
    app_mqtt_init();
    return device;
}
//发送远程消息的任务函数，县城池中的分线程调用
int send_task_func(void *arg)
{
    Device *dev = (Device *)arg;
    //从上行缓冲区读取一个字符数组消息数据
    char chars_buff[128];
    int len = app_buffer_read(dev->up_buf, chars_buff, sizeof(chars_buff));
    //转换为json格式消息
    char *json = app_message_charsToJson(chars_buff, len);
    //发送消息得到远程
    int result = app_mqtt_send(json);
    if (result == -1)
    {
        log_debug("发送消息到远程失败");
        return -1;
    }
    //记录发送时间
    log_debug("发送消息到远程成功: %s",json);
    return 0;
    
    
}
//读线程
static void  *read_thread_func(void *arg)
{
    //循环读取数据
    while(device->is_running)
    {
        char data_buff[128];
        //读取数据
       ssize_t data_len =  read(device->fd, data_buff, sizeof(data_buff));
        //如果有数据，且制定了读后处理函数，则调用读后处理
        if(data_len > 0 && device->post_read)
        {
           data_len =  device->post_read(data_buff, data_len);
        }
        if (data_len > 0)
        {
            //将字符数组数据写入上行缓冲区
            app_buffer_write(device->up_buf, data_buff, data_len);
            //将上行缓冲区读取数据的任务交给县城池完成
            app_pool_registerTask(send_task_func, device);
        }
    }
}
int write_task_func(void *arg)
{
    //从下行缓冲区读取一个字符数组消息数据
    char chars_buff[128];
    int len = app_buffer_read(device->down_buf, chars_buff, sizeof(chars_buff));
    if (len == -1)
    {
        log_error("从下行缓冲区读取数据失败");
        return -1;
    }
    //如果制定了写前处理函数，则调用处理 -》转换为蓝牙格式的数据
    if (device->post_write)
    {
       len = device->post_write(chars_buff, len);
    }
    //如果与上一次写的时间小于200ms，则等待相关时间
    long distance_time = app_common_getCurrentTime() - device->last_write_time;
    if (distance_time < 200)
    {
        usleep(200 - distance_time * 1000);
    }
    //写到串口文件中
   ssize_t result =  write(device->fd, chars_buff, len);
    if (result != len)
    {
       log_error("写入失败");
        return -1;
    }
    log_debug("写入成功: %.*s",len, chars_buff);

    //最后一次写的时间
    device->last_write_time = app_common_getCurrentTime();
    return 0;
}
//接受远程消息的回调函数
static int receice_msg_callback(char *json)
{
    //将json格式消息转换为字符数组消息
    char chars_buff[128];
    int len = app_message_jsonToChars(json, chars_buff, sizeof(chars_buff));
    //将字符数组消息写入下行缓冲区
    app_buffer_write(device->down_buf, chars_buff, len);
    //将下行缓冲区读川口的任务交给县城池完成‘
    app_pool_registerTask(write_task_func,NULL);
    return 0;
    
}
//启动设备
int app_device_start()
{
  
    if (device->is_running == 1)
    {
        log_debug("设备已经启动,无需重复启动");
        return 0;
    }

    device->is_running = 1;
    //启动线程
    pthread_create(&device->read_thread, NULL, read_thread_func, NULL);

    //注册接受远程消息的回调函数
    app_mqtt_regist_recv_cb(receice_msg_callback);
    }
//销毁设备
void app_device_destroy()
{
    //关闭文件
    close(device->fd);
    //释放缓冲区
    app_buffer_free(device->up_buf);
    app_buffer_free(device->down_buf);
    //取消停止度线程
    pthread_cancel(device->read_thread);
    //等待线程结束
    pthread_join(device->read_thread, NULL);

    //释放内存
    free(device);
    //释放线程池
    app_pool_destroy();
    //释放客户段
    app_mqtt_close();
}